package org.light.domain;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.light.core.ApplicationContextXml;
import org.light.core.DotClassPathXml;
import org.light.core.DotProjectXml;
import org.light.core.Log4jProperties;
import org.light.core.POMXml;
import org.light.core.SettingEclipseJdtPrefs;
import org.light.core.SettingEclipsePrefs;
import org.light.core.SettingEclipseSuperTypeContainer;
import org.light.core.SettingEclipseSuperTypeName;
import org.light.core.SettingEclipseWstFacetXml;
import org.light.core.SettingJsdtScopeXml;
import org.light.core.SettingWstComponentXml;
import org.light.core.SpringMVCController;
import org.light.core.SpringMVCXml;
import org.light.core.WebXml;
import org.light.easyui.EasyUIHomePageTemplate;
import org.light.exception.ValidateException;
import org.light.generator.ApplicationDevPropertiesGenerator;
import org.light.generator.ApplicationJavaGenerator;
import org.light.generator.ApplicationProdPropertiesGenerator;
import org.light.generator.ApplicationPropertiesGenerator;
import org.light.generator.DBDefinitionGenerator;
import org.light.generator.IndexControllerJavaGenerator;
import org.light.generator.JsonPagingGridJspTemplate;
import org.light.generator.MSExcelUtilGenerator;
import org.light.generator.MysqlTwoDomainsDBDefinitionGenerator;
import org.light.generator.PDFUtilGenerator;
import org.light.generator.POIExcelUtilGenerator;
import org.light.generator.StringUtilGenerator;
import org.light.include.Footer;
import org.light.include.Header;
import org.light.include.JsonUserNav;
import org.light.include.JumpHomePage;
import org.light.include.Updates;
import org.light.oracle.core.OraclePrism;
import org.light.oracle.generator.Oracle11gSqlReflector;
import org.light.utils.SqlReflector;
import org.light.utils.StringUtil;
import org.light.utils.ZipCompressor;

import net.sf.json.JSONObject;

public class Project implements Serializable{
	protected long projectId;
	protected String standardName;
	protected String packageToken;
	protected String technicalstack;
	protected long namingId;
	protected Naming naming;
	protected String folderPath = "D:/JerryWork/Infinity/testFiles/";
	protected String sourceFolderPath = "D:/JerryLunaWorkspace/InfinityGPGenerator/WebContent/templates/";
	protected List<Prism> prisms = new ArrayList<Prism>();
	protected List<Util> utils = new ArrayList<Util>();
	protected Set<Independent> independents = new TreeSet<Independent>();
	protected List<Include> includes = new ArrayList<Include>();
	protected List<Include> jsonIncludes = new ArrayList<Include>();
	protected List<DBDefinitionGenerator> dbDefinitionGenerators = new ArrayList<DBDefinitionGenerator>();
	protected String dbName;
	protected TestSuite projectTestSuite = new TestSuite();
	protected List<ConfigFile> configFiles = new ArrayList<ConfigFile>();
	protected Set<IndependentConfig> independentConfigs = new TreeSet<IndependentConfig>();
	protected List<Domain> domains = new ArrayList<Domain>();
	protected String dbPrefix = "";
	protected String dbUsername = "root";
	protected String dbPassword = "";
	protected String dbType="mysql";
	protected boolean emptypassword = false;
	protected EasyUIHomePageTemplate homepage = new EasyUIHomePageTemplate();
	protected JumpHomePage jumphomepage = new JumpHomePage();
	protected String sgsSource;
	protected String sqlSource;
	protected String label;
	protected List<MysqlTwoDomainsDBDefinitionGenerator> myTwoDBGenerators = new ArrayList<MysqlTwoDomainsDBDefinitionGenerator>();
	protected List<List<Domain>> dataDomains = new ArrayList<>();
	protected String excelTemplateName = "";
	protected String excelTemplateFolder = "";
	protected String title = "";
	protected String subTitle = "";
	protected String footer = "";
	protected String crossOrigin = "";
	protected String resolution = "low";
	
	public String getResolution() {
		return resolution;
	}

	public void setResolution(String resolution) {
		this.resolution = resolution;
	}

	public String getSgsSource() {
		return sgsSource;
	}

	public void setSgsSource(String sgsSource) {
		this.sgsSource = sgsSource;
	}

	public String getSqlSource() {
		return sqlSource;
	}

	public void setSqlSource(String sqlSource) {
		this.sqlSource = sqlSource;
	}

	public boolean isEmptypassword() {
		return emptypassword;
	}

	public void setEmptypassword(boolean emptypassword) {
		this.emptypassword = emptypassword;
	}

	public Project(){
		super();
	}

	public List<Include> getJsonIncludes() {
		return jsonIncludes;
	}

	public void setJsonIncludes(List<Include> jsonIncludes) {
		this.jsonIncludes = jsonIncludes;
	}
	
	public Project(String projectName,String packageToken, String technicalStack,String dbUsername, String dbPassword, boolean emptyPassword, String dbname) throws ValidateException {
		this(projectName,packageToken,technicalStack,dbUsername,dbPassword,emptyPassword,dbname,"mysql");
	}
		
	
	public Project(String projectName,String packageToken, String technicalStack,String dbUsername, String dbPassword, boolean emptyPassword, String dbname,String dbType) throws ValidateException {
		super();
		if (packageToken == null || packageToken.equals("")||dbname == null || dbname.equals("")|| dbUsername == null || dbUsername.equals("")){
			throw new ValidateException("项目参数为空，通不过校验！");
		}
		this.standardName = projectName;
		this.packageToken = packageToken;
		this.technicalstack = technicalStack;
		this.emptypassword = emptyPassword;
		this.dbUsername = dbUsername;
		this.dbPassword = dbPassword;
		this.dbName = dbname;
		this.dbType = dbType;
		if (technicalStack==null || technicalStack.equals("")|| technicalStack.equalsIgnoreCase("sbmeu")){
			if (dbType.equals("mysql")){
				this.setTechnicalstack("sbmeu");
				WebXml webxml = new WebXml();
				webxml.setPackageToken(packageToken);
				webxml.setProjectName(this.getStandardName());
				webxml.setStandardName("web.xml");
				addConfigFile(webxml);
				
				POMXml pomxml = new POMXml();
				pomxml.setProjectName(projectName);
				pomxml.setFolder("");
				addIndependentConfig(pomxml);
				
				ApplicationJavaGenerator appj = new ApplicationJavaGenerator();
				appj.setPackageToken(packageToken);
				addIndependent(appj);
				
				IndexControllerJavaGenerator idc = new IndexControllerJavaGenerator();
				idc.setPackageToken(packageToken+".controller");
				addIndependent(idc);
				
				ApplicationProdPropertiesGenerator apppg = new ApplicationProdPropertiesGenerator();
				apppg.setProjectName(projectName);
				addIndependentConfig(apppg);
				
				ApplicationDevPropertiesGenerator appdg = new ApplicationDevPropertiesGenerator();
				appdg.setProjectName(projectName);
				addIndependentConfig(appdg);
				
				ApplicationPropertiesGenerator appg = new ApplicationPropertiesGenerator();
				appg.setDbType(dbType);
				appg.setDbName(dbname);
				appg.setDbUserName(this.dbUsername);
				appg.setDbUserPassword(this.dbPassword);
				appg.setPackageToken(packageToken);
				addIndependentConfig(appg);			
				
				List<SpringMVCController> myControllers = new ArrayList<SpringMVCController>();
				for (Prism p:this.prisms){
					myControllers.add(p.getController());
				}
				
				ApplicationContextXml axml = new ApplicationContextXml(packageToken,this.dbName,dbUsername,dbPassword);
				if (emptyPassword) axml.setDbPassword("");
				axml.setDomainList(this.domains);
				TreeSet<SpringMVCController> myFSet = new TreeSet<SpringMVCController>();
				myFSet.addAll(myControllers);
				axml.setControllers(myFSet);
				List<String> packageToScanList = new ArrayList<String>();
				packageToScanList.add(this.packageToken+".domain");
				axml.setPackagesToScanList(packageToScanList);
				axml.setPutInsideSrcAndClasses(true);
				replaceConfigFile(axml);
				
				SpringMVCXml smxml = new SpringMVCXml();
				smxml.setPackageToken(packageToken);
				addConfigFile(smxml);
				
				Log4jProperties log4j = new Log4jProperties();
				log4j.setPutInsideSrcAndClasses(true);
				addConfigFile(log4j);
				
				DotProjectXml dpxml = new DotProjectXml();
				dpxml.setProjectName(projectName);
				addConfigFile(dpxml);
				
				DotClassPathXml dcpxml = new DotClassPathXml();
				addConfigFile(dcpxml);
				
				SettingJsdtScopeXml sscopexml = new SettingJsdtScopeXml();
				addConfigFile(sscopexml);
				
				SettingEclipseJdtPrefs sejPrefs = new SettingEclipseJdtPrefs();
				addConfigFile(sejPrefs);
				
				SettingEclipsePrefs sePrefs = new SettingEclipsePrefs();
				addConfigFile(sePrefs);
				
				SettingEclipseSuperTypeContainer sContainer = new SettingEclipseSuperTypeContainer();
				addConfigFile(sContainer);
				
				SettingEclipseSuperTypeName sSuperTypeName = new  SettingEclipseSuperTypeName();
				addConfigFile(sSuperTypeName);
				
				SettingEclipseWstFacetXml sFacetXml = new SettingEclipseWstFacetXml();
				addConfigFile(sFacetXml);
				
				SettingWstComponentXml sComponentXml = new SettingWstComponentXml();
				sComponentXml.setProjectName(projectName);
				addConfigFile(sComponentXml);
				
				addJsonInclude(new Header());
				addJsonInclude(new Footer());
				addJsonInclude(new Updates());
				addJsonInclude(new JsonUserNav(this.domains));
				
				addUtil(new BooleanUtil(packageToken));
				addUtil(new StringUtilGenerator(packageToken));
				addUtil(new POIExcelUtilGenerator(packageToken));
				addUtil(new PDFUtilGenerator(packageToken));
				addUtil(new MSExcelUtilGenerator(packageToken));
			} else if (dbType.equals("oracle")){
				this.setTechnicalstack("sbmeu");
				WebXml webxml = new WebXml();
				webxml.setPackageToken(packageToken);
				webxml.setProjectName(this.getStandardName());
				webxml.setStandardName("web.xml");
				addConfigFile(webxml);
				
				POMXml pomxml = new POMXml(dbType);
				pomxml.setProjectName(projectName);
				pomxml.setFolder("");
				addIndependentConfig(pomxml);
				
				ApplicationJavaGenerator appj = new ApplicationJavaGenerator();
				appj.setPackageToken(packageToken);
				addIndependent(appj);
				
				IndexControllerJavaGenerator idc = new IndexControllerJavaGenerator();
				idc.setPackageToken(packageToken+".controller");
				addIndependent(idc);
				
				ApplicationProdPropertiesGenerator apppg = new ApplicationProdPropertiesGenerator();
				apppg.setProjectName(projectName);
				addIndependentConfig(apppg);
				
				ApplicationDevPropertiesGenerator appdg = new ApplicationDevPropertiesGenerator();
				appdg.setProjectName(projectName);
				addIndependentConfig(appdg);
				
				ApplicationPropertiesGenerator appg = new ApplicationPropertiesGenerator();
				appg.setDbType(dbType);
				appg.setDbName(dbname);
				appg.setDbUserName(this.dbUsername);
				appg.setDbUserPassword(this.dbPassword);
				appg.setPackageToken(packageToken);
				addIndependentConfig(appg);
				
				List<SpringMVCController> myControllers = new ArrayList<SpringMVCController>();
				for (Prism p:this.prisms){
					myControllers.add(p.getController());
				}
				
				ApplicationContextXml axml = new ApplicationContextXml(packageToken,this.dbName,dbUsername,dbPassword,dbType);
				if (emptyPassword) axml.setDbPassword("");
				axml.setDomainList(this.domains);
				TreeSet<SpringMVCController> myFSet = new TreeSet<SpringMVCController>();
				myFSet.addAll(myControllers);
				axml.setControllers(myFSet);
				List<String> packageToScanList = new ArrayList<String>();
				packageToScanList.add(this.packageToken+".entity");
				axml.setPackagesToScanList(packageToScanList);
				axml.setPutInsideSrcAndClasses(true);
				replaceConfigFile(axml);
				
				SpringMVCXml smxml = new SpringMVCXml();
				smxml.setPackageToken(packageToken);
				addConfigFile(smxml);
				
				Log4jProperties log4j = new Log4jProperties();
				log4j.setPutInsideSrcAndClasses(true);
				addConfigFile(log4j);
				
				DotProjectXml dpxml = new DotProjectXml();
				dpxml.setProjectName(projectName);
				addConfigFile(dpxml);
				
				DotClassPathXml dcpxml = new DotClassPathXml();
				addConfigFile(dcpxml);
				
				SettingJsdtScopeXml sscopexml = new SettingJsdtScopeXml();
				addConfigFile(sscopexml);
				
				SettingEclipseJdtPrefs sejPrefs = new SettingEclipseJdtPrefs();
				addConfigFile(sejPrefs);
				
				SettingEclipsePrefs sePrefs = new SettingEclipsePrefs();
				addConfigFile(sePrefs);
				
				SettingEclipseSuperTypeContainer sContainer = new SettingEclipseSuperTypeContainer();
				addConfigFile(sContainer);
				
				SettingEclipseSuperTypeName sSuperTypeName = new  SettingEclipseSuperTypeName();
				addConfigFile(sSuperTypeName);
				
				SettingEclipseWstFacetXml sFacetXml = new SettingEclipseWstFacetXml();
				addConfigFile(sFacetXml);
				
				SettingWstComponentXml sComponentXml = new SettingWstComponentXml();
				sComponentXml.setProjectName(projectName);
				addConfigFile(sComponentXml);
				
				addJsonInclude(new Header());
				addJsonInclude(new Footer());
				addJsonInclude(new Updates());
				addJsonInclude(new JsonUserNav(this.domains));
				
				addUtil(new BooleanUtil(packageToken));
				addUtil(new StringUtilGenerator(packageToken));
				addUtil(new POIExcelUtilGenerator(packageToken));
				addUtil(new PDFUtilGenerator(packageToken));
				addUtil(new MSExcelUtilGenerator(packageToken));
			}else {
				throw new ValidateException("项目所用的数据库未被支持。");
			}
		}
	}
	
	private void addIndependent(Independent idt) {
		this.independents.add(idt);		
	}

	private void addIndependentConfig(IndependentConfig idc) {
		this.independentConfigs.add(idc);
	}

	public void decorateMentuItems(){
		Set<ManyToMany> manyToManies = new TreeSet<ManyToMany>();
		for (Prism p:this.prisms){
			manyToManies.addAll(p.getManyToManies());
		}	
		Set<MenuItem> menuItems = new TreeSet<MenuItem>();
		for (Prism p:this.prisms){
			for (ManyToMany mtm:p.getManyToManies()){
				mtm.getEuTemplate().setMenuDomainList(this.domains);					
			}
			
			for (ManyToMany mtm:manyToManies){
				MenuItem mi = new MenuItem("../pages/"+mtm.getStandardName().toLowerCase()+".html",mtm.getStandardName(),mtm.getText());
				menuItems.add(mi);
			}
		}
		for (Prism p:this.prisms){
			for (JsonPagingGridJspTemplate jtp:p.getJsonjsptemplates()) {
				jtp.setMenuItems(menuItems);
			}
			for (ManyToMany mtm:p.getManyToManies()){
				mtm.getEuTemplate().setMenuItems(menuItems);
			}
		}
		for (ManyToMany mtm:manyToManies){
			this.myTwoDBGenerators.add(mtm.toTwoDBGenerator());
		}
		this.homepage.setMenuItems(menuItems);
	}

	public ConfigFile findConfigFile(String standardName){
		if (this.configFiles != null && this.configFiles.size()>0){
			for (ConfigFile c : this.configFiles){
				if (c.getStandardName().equals(standardName)) return c;
			}
		}
		return null;
	}
	
	public List<Util> getUtils() {
		return utils;
	}
	public void setUtils(List<Util> utils) {
		this.utils = utils;
	}
	
	public void addUtil(Util util){
		this.utils.add(util);
	}
	
	public void addInclude(Include include){
		this.includes.add(include);
	}
	
	public void addJsonInclude(Include include){
		this.jsonIncludes.add(include);
	}
	
	public long getProjectId() {
		return projectId;
	}
	public void setProjectId(long projectId) {
		this.projectId = projectId;
	}
	public String getStandardName() {
		return standardName;
	}
	public void setStandardName(String standardName) {
		this.standardName = standardName;
		//this.homepage.setPageTitile("Welcome to the " + StringUtil.capFirst(standardName)+ " System.");
		WebXml webxml = (WebXml)findConfigFile("web.xml");
		if (webxml != null)
			webxml.setProjectName(standardName);
	}
	public long getNamingId() {
		return namingId;
	}
	public void setNamingId(long namingId) {
		this.namingId = namingId;
	}
	public Naming getNaming() {
		return naming;
	}
	public void setNaming(Naming naming) {
		this.naming = naming;
	}
	public List<Prism> getPrisms() {
		return prisms;
	}
	public void setPrisms(List<Prism> prisms) {
		if (this.technicalstack == null || "".equals(this.technicalstack) ||"sbmeu".equalsIgnoreCase(this.technicalstack)){				
			this.prisms = prisms;
			if (this.technicalstack==null || this.technicalstack.equals("")|| this.technicalstack.equalsIgnoreCase("sbmeu")){
				//WebXml webxml = (WebXml)this.findConfigFile("web.xml");
				this.prisms = prisms;
				ApplicationContextXml axml = (ApplicationContextXml)this.findConfigFile("applicationContext.xml");
				for (Prism prism:prisms){				
					
					for (JsonPagingGridJspTemplate jp: prism.getJsonjsptemplates()){
						JsonUserNav jn = new JsonUserNav(this.domains);
						jp.setJsonUserNav(jn);
						jp.setAllDomainList(this.domains);
					}					
				}
				this.homepage.setAllDomainList(this.domains);
			}
		}
	}
	
	public void addPrism(Prism prism){	
		if (this.packageToken != null) prism.setPackageToken(this.packageToken);
		this.prisms.add(prism);
	}
	
	public String getPackageToken() {
		return packageToken;
	}
	public void setPackageToken(String packageToken) {
		this.packageToken = packageToken;
		for (Util u: this.utils){
			u.setPackageToken(packageToken);
		}
		WebXml webxml = (WebXml)findConfigFile("web.xml");
		if (webxml != null)
			webxml.setPackageToken(packageToken);
	}
	
	public void generateProjectFiles() throws Exception {
		if (this.dbType==null ||"".equals(this.dbType)||"mysql".equals(this.dbType)){
			ValidateInfo info = this.validate();
			if (info.success() == false) {
				throw new ValidateException(info);
			}
			try {
				decorateMentuItems();
				String srcfolderPath = this.getProjectFolderPath();
	
				for (Prism ps : this.prisms) {
					ps.setFolderPath(this.getProjectFolderPath());
					ps.generatePrismFiles();
				}
				for (Util u : utils) {
					String utilPath = this.getProjectFolderPath() + "src/main/java/" + packagetokenToFolder(u.getPackageToken())
							+ "utils/";
					writeToFile(utilPath + u.getFileName(), u.generateUtilString());
				}
				
				for (Independent idt : this.independents) {
					String idtPath = this.getProjectFolderPath() + "src/main/java/" + packagetokenToFolder(idt.getPackageToken());
					writeToFile(idtPath + idt.getFileName(), idt.generateImplString());
				}
	
				String homePath = this.getProjectFolderPath() + "src/main/resources/static/";
				writeToFile(homePath + "index.html", this.jumphomepage.generateIncludeString());
	
				homePath = this.getProjectFolderPath() + "src/main/resources/static/pages/";
				writeToFile(homePath + "index.html", this.homepage.generateStatementList().getContent());
	
				FileCopyer copy = new FileCopyer();
	
				File cssfrom = new File(this.getSourceFolderPath() + "css/");
				File cssto = new File(this.getProjectFolderPath() + "src/main/resources/static/css/");
	
				copy.dirFrom = cssfrom;
				copy.dirTo = cssto;
				copy.listFileInDir(cssfrom);
	
				File jsfrom = new File(this.getSourceFolderPath() + "js/");
				File jsto = new File(this.getProjectFolderPath() + "src/main/resources/static/js/");
	
				copy.dirFrom = jsfrom;
				copy.dirTo = jsto;
				copy.listFileInDir(jsfrom);
	
				File easyuifrom = new File(this.getSourceFolderPath() + "easyui/");
				File easyuito = new File(this.getProjectFolderPath() + "src/main/resources/static/easyui/");
	
				copy.dirFrom = easyuifrom;
				copy.dirTo = easyuito;
				copy.listFileInDir(easyuifrom);
				
				if (!StringUtil.isBlank(this.getExcelTemplateName())){				
					File mF1 = new File((this.getExcelTemplateFolder()+this.getExcelTemplateName()).replace("\\", "/"));
					File mF2 = new File((this.getProjectFolderPath() + "exceltemplate/"+this.getExcelTemplateName()).replace("\\", "/"));
					if (mF1.exists()){
						if (!mF2.getParentFile().exists()){
							mF2.getParentFile().mkdirs();
						}
						if (!mF2.exists()){
							mF2.createNewFile();
						}
						copy.copy(mF1.getPath(), mF2.getPath());
					}
				}
	
				StringBuilder sql = new StringBuilder();
				boolean createNew = true;
				for (DBDefinitionGenerator dbd : dbDefinitionGenerators) {
					sql.append(dbd.generateDBSql(createNew)).append("\n");
					if (createNew)
						createNew = false;
				}
				for (MysqlTwoDomainsDBDefinitionGenerator mtg:this.myTwoDBGenerators){
					sql.append(mtg.generateDBSql(this.getDbType()));
				}
				
				for (List<Domain> dataDomains : this.getDataDomains()){
					sql.append("\n");
					for (Domain d: dataDomains){
						sql.append(SqlReflector.generateInsertSqlWithValue(d)).append("\n");
					}
					
					for (Domain d: dataDomains){
						for (ManyToMany mtm:d.getManyToManies()){
							sql.append(SqlReflector.generateMtmInsertSqlWithValues(mtm)).append("\n");
						}
					}
				}		
				
				writeToFile(this.getProjectFolderPath() + "sql/" + this.getStandardName() + ".sql", sql.toString());
				
				for (IndependentConfig idc:this.independentConfigs) {
					writeToFile(this.getProjectFolderPath() + idc.getFolder()+idc.getFileName(),
							idc.generateImplString());
				}
				
//				for (ConfigFile cf : this.configFiles) {
//					if (cf.isTopLevel()) {
//						writeToFile(this.getProjectFolderPath() + cf.getStandardName(), cf.generateConfigFileString());
//					} else if (cf.isSettingParamFile()) {
//						writeToFile(this.getProjectFolderPath() + ".settings/" + cf.getStandardName(),
//								cf.generateConfigFileString());
//					} else if (cf.isPutInsideSrcAndClasses == false) {
//						writeToFile(this.getProjectFolderPath() + "src/main/resources/static/WEB-INF/" + cf.getStandardName(),
//								cf.generateConfigFileString());
//					} else {
//						writeToFile(this.getProjectFolderPath() + "src/main/java/" + cf.getStandardName(),
//								cf.generateConfigFileString());
//					}
//				}
			} catch (Exception e) {
				e.printStackTrace();
				throw e;
			}
		} else if ("oracle".equals(this.dbType)){
			ValidateInfo info = this.validate();
			if (info.success() == false) {
				for (String s : info.getCompileErrors()) {
					System.out.println(s);
				}
				return;
			}
			try {
				decorateMentuItems();
				String projectFolderPath = this.getProjectFolderPath().replace('\\', '/');
				String templateFolderPath = this.getSourceFolderPath().replace('\\', '/');
				if (this.getSgsSource() != null && !this.getSgsSource().equals("")) {
					writeToFile(projectFolderPath + "sgs/"+StringUtil.capFirst(this.getStandardName()) + "_original.sgs",
							this.getSgsSource());
				}
	
				/*for (Domain d : this.domains) {
					writeToFile(projectFolderPath + d.getStandardName() + ".java", d.generateClassString());
				}*/
				for (Prism ps : this.prisms) {
 					OraclePrism ops = (OraclePrism) ps;
					ops.setFolderPath(projectFolderPath);					
					ops.generatePrismFiles();
				}
				for (Util u : utils) {
					String utilPath = projectFolderPath + "src/main/java/" + packagetokenToFolder(u.getPackageToken())
							+ "utils/";
					writeToFile(utilPath +u.getFileName(), u.generateUtilString());
				}
				for (Independent idt : this.independents) {
					String idtPath = this.getProjectFolderPath() + "src/main/java/" + packagetokenToFolder(idt.getPackageToken());
					writeToFile(idtPath + idt.getFileName(), idt.generateImplString());
				}
	
				String homePath = projectFolderPath + "src/main/resources/static/";
				writeToFile(homePath + "index.html", this.jumphomepage.generateIncludeString());
	
				homePath = projectFolderPath + "src/main/resources/static/pages/";
				this.homepage.setTitle(this.getTitle());
				this.homepage.setSubTitle(this.getSubTitle());
				this.homepage.setFooter(this.getFolderPath());
				this.homepage.setResolution(this.getResolution());
				writeToFile(homePath + "index.html", this.homepage.generateStatementList().getContent());
	
				FileCopyer copy = new FileCopyer();				
				
				File libto = new File(this.getProjectFolderPath() + "src/main/webapp/WEB-INF/lib/");
				File libfrom = new File(this.getSourceFolderPath() + "lib/");

				copy.dirFrom = libfrom;
				copy.dirTo = libto;
				copy.listFileInDir(libfrom);
	
				File cssfrom = new File(templateFolderPath + "css/");
				File cssto = new File(projectFolderPath + "src/main/resources/static/css/");
	
				copy.dirFrom = cssfrom;
				copy.dirTo = cssto;
				copy.listFileInDir(cssfrom);
	
				File jsfrom = new File(templateFolderPath + "js/");
				File jsto = new File(projectFolderPath + "src/main/resources/static/js/");
	
				copy.dirFrom = jsfrom;
				copy.dirTo = jsto;
				copy.listFileInDir(jsfrom);
	
				File easyuifrom = new File(templateFolderPath + "easyui/");
				File easyuito = new File(projectFolderPath + "src/main/resources/static/easyui/");
	
				copy.dirFrom = easyuifrom;
				copy.dirTo = easyuito;
				copy.listFileInDir(easyuifrom);
				
				if (!StringUtil.isBlank(this.getExcelTemplateName())){				
					File mF1 = new File((this.getExcelTemplateFolder()+this.getExcelTemplateName()).replace("\\", "/"));
					File mF2 = new File((projectFolderPath + "exceltemplate/"+this.getExcelTemplateName()).replace("\\", "/"));
					if (mF1.exists()){
						if (!mF2.getParentFile().exists()){
							mF2.getParentFile().mkdirs();
						}
						if (!mF2.exists()){
							mF2.createNewFile();
						}
						copy.copy(mF1.getPath(), mF2.getPath());
					}
				}	
	
				StringBuilder sql = new StringBuilder();
				boolean createNew = false;
				for (DBDefinitionGenerator dbd : dbDefinitionGenerators) {
					sql.append(dbd.generateDropTableSqls(createNew));
				}
				
				for (MysqlTwoDomainsDBDefinitionGenerator mtg:this.myTwoDBGenerators){
					sql.append(mtg.generateDropLinkTableSql());
				}
				
				sql.append("\n\n");				
				
				sql.append("drop sequence COMMONSEQUENCE;").append("\n\n");
				sql.append("-- Create sequence").append("\n") 
				.append("create sequence COMMONSEQUENCE").append("\n") 
				.append("minvalue 10000").append("\n") 
				.append("maxvalue 9999999999999999999999999999").append("\n") 
				.append("start with 10000").append("\n") 
				.append("increment by 1").append("\n") 
				.append("cache 20;").append("\n\n");
				
				for (DBDefinitionGenerator dbd : dbDefinitionGenerators) {
					sql.append(dbd.generateDBSql(createNew)).append("\n");
				}
				for (MysqlTwoDomainsDBDefinitionGenerator mtg:this.myTwoDBGenerators){
					sql.append(mtg.generateDBSql(this.getDbType()));
				}				
				
				// load initial data
				for (List<Domain> dataDomains : this.getDataDomains()){
					sql.append("\n");
					for (Domain d: dataDomains){
						sql.append(Oracle11gSqlReflector.generateInsertSqlWithValue(d)).append("\n");
					}
					

					for (Domain d: dataDomains){
						for (ManyToMany mtm:d.getManyToManies()){
							sql.append(Oracle11gSqlReflector.generateMtmInsertSqlWithValues(mtm)).append("\n");
						}
					}
				}	
				
				writeToFile(projectFolderPath+"sql/"+this.standardName + ".sql", sql.toString());
	
				for (IndependentConfig idc:this.independentConfigs) {
					writeToFile(this.getProjectFolderPath() + idc.getFolder()+idc.getFileName(),
							idc.generateImplString());
				}
			} catch (Exception e) {
				e.printStackTrace();
				throw e;
			}
			} else {
			ValidateInfo info = new ValidateInfo();
			info.addCompileError("未支持项目所用数据库。");
			throw new ValidateException(info);
		}
	}
	
	public String getSourceFolderPath() {
		return sourceFolderPath;
	}

	public void setSourceFolderPath(String sourceFolderPath) {
		this.sourceFolderPath = sourceFolderPath;
	}

	public void generateProjectZip() throws Exception{
		delAllFile(this.folderPath+this.standardName+".zip");
		delFolder(this.getProjectFolderPath());
		File f = new File(this.getProjectFolderPath());
		if (!f.getParentFile().exists()) {
			f.getParentFile().mkdirs();
		}
		f.mkdirs();
				
		generateProjectFiles();
		ZipCompressor compressor = new ZipCompressor(this.folderPath+this.standardName+".zip");
		compressor.compressExe(this.getProjectFolderPath());
		delFolder(this.getProjectFolderPath());
	}
	
	public String getFolderPath() {
		return this.folderPath;
	}
	
	public String getProjectFolderPath(){
		if ( this.getStandardName()!= null && !"".equals(this.getStandardName())){
			return folderPath + this.getStandardName() + "/";
		}
		else return folderPath;
	}
	public void setFolderPath(String folderPath) {
		this.folderPath = folderPath;
	}
	
	public static String packagetokenToFolder(String packageToken){
		String folder = "";
		if (packageToken != null)
			 folder = packageToken.replace('.','/');
		folder += "/";
		return folder;
	}
	
	public static String folderToPackageToken(String folder){
		String packagetoken = folder.replace('/', '.');
		if (packagetoken.charAt(packagetoken.length()-1) == '.')
			packagetoken = packagetoken.substring(0, packagetoken.length() -1);
		return packagetoken;
	}
	public List<DBDefinitionGenerator> getDbDefinitionGenerators() {
		return dbDefinitionGenerators;
	}
	public void setDbDefinitionGenerators(
			List<DBDefinitionGenerator> dbDefinitionGenerators) {
		this.dbDefinitionGenerators = dbDefinitionGenerators;
	}
	
	public void addDBDefinitionGenerator(DBDefinitionGenerator generator){
		this.dbDefinitionGenerators.add(generator);
	}
	public String getDbName() {
		return dbName;
	}
	
	public void setDbName(String dbName) {
		this.dbName = dbName;
	}	
	
	public TestSuite getProjectTestSuite() {
		return projectTestSuite;
	}
	public void setProjectTestSuite(TestSuite projectTestSuite) {
		this.projectTestSuite = projectTestSuite;
	}
	
	public void addTestSuite(TestSuite testSuite){
		this.projectTestSuite.testSuites.add(testSuite);
	}
	
	public void addTestCase(TestCase testCase){
		this.projectTestSuite.testCases.add(testCase);
	}
	
	public void addTestCases(List<TestCase> testCases){
		this.projectTestSuite.testCases.addAll(testCases);
	}
	public List<ConfigFile> getConfigFiles() {
		return configFiles;
	}
	public void setConfigFiles(List<ConfigFile> configFiles) {
		this.configFiles = configFiles;
	}
	
	public void addConfigFile(ConfigFile configFile){
		this.configFiles.add(configFile);
	}
	
	public void addConfigFiles(List<ConfigFile> configFiles){
		this.configFiles.addAll(configFiles);
	}
	
	public static void zipFile(File inFile, ZipOutputStream zos, String dir) throws IOException {
		if (inFile.isDirectory()) {
			File[] files = inFile.listFiles();
			for (File file:files)
				zipFile(file, zos, dir + "/" + inFile.getName());
		} else {
			String entryName = null;
			if (!"".equals(dir))
				entryName = dir + "/" + inFile.getName();
			else
				entryName = inFile.getName();
			ZipEntry entry = new ZipEntry(entryName);
			zos.putNextEntry(entry);
			InputStream is = new FileInputStream(inFile);
			int len = 0;
			while ((len = is.read()) != -1)
				zos.write(len);
			is.close();
		}
	}

	public static void delFolder(String folderPath) {
		try {
			delAllFile(folderPath); // 删除完里面所有内容
			String filePath = folderPath;
			filePath = filePath.toString();
			java.io.File myFilePath = new java.io.File(filePath);
			myFilePath.delete(); // 删除空文件夹
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static boolean delAllFile(String path) {
		boolean flag = false;
		File file = new File(path);
		if (!file.exists()) {
			return flag;
		}
		if (!file.isDirectory()) {
			return flag;
		}
		String[] tempList = file.list();
		File temp = null;
		for (int i = 0; i < tempList.length; i++) {
			if (path.endsWith(File.separator)) {
				temp = new File(path + tempList[i]);
			} else {
				temp = new File(path + File.separator + tempList[i]);
			}
			if (temp.isFile()) {
				temp.delete();
			}
			if (temp.isDirectory()) {
				delAllFile(path + "/" + tempList[i]);// 先删除文件夹里面的文件
				delFolder(path + "/" + tempList[i]);// 再删除空文件夹
				flag = true;
			}
		}
		return flag;
	}
	
	public ValidateInfo validate(){
		ValidateInfo info = new ValidateInfo();
		for (Domain d: this.domains){
			ValidateInfo v = d.validate(this.getDbType());
			if (v.success() == false){
				info.setSuccess(false);
				info.addAllCompileErrors(v.getCompileErrors());
				info.addAllCompileWarnings(v.getCompileWarnings());
			}
		}
		for (Prism ps:this.prisms){
			ValidateInfo v = ps.validate();
			info.addAllCompileErrors(v.getCompileErrors());
			info.addAllCompileWarnings(v.getCompileWarnings());
		}
		return info;
	}
	public List<Domain> getDomains() {
		return domains;
	}
	public void setDomains(List<Domain> domains) {		
		for (Domain d: domains){
			this.addDomain(d);
			for (Include include:this.includes){
				include.addDomain(d);
			}
		}
	}
	
	public void addDomain(Domain domain){
		if (this.getDbPrefix() != null && !this.getDbPrefix().equals("")) {
			domain.setDbPrefix(this.getDbPrefix());	
		}
		this.domains.add(domain);
		for (Include include:this.includes){
			include.addDomain(domain);
		}
	}

	public String getDbPrefix() {
		return dbPrefix;
	}

	public void setDbPrefix(String dbPrefix) {
		this.dbPrefix = dbPrefix;
		for (Domain d:this.getDomains()){
			d.setDbPrefix(dbPrefix);
		}
		for (Prism p: this.getPrisms()){
			p.getDomain().setDbPrefix(dbPrefix);
		}
	
	}

	public String getTechnicalstack() {
		return technicalstack;
	}

	public void setTechnicalstack(String technicalstack) {
		this.technicalstack = technicalstack;
	}

	public List<Include> getIncludes() {
		return includes;
	}

	public void setIncludes(List<Include> includes) {
		this.includes = includes;
	}

	public JumpHomePage getJumphomepage() {
		return jumphomepage;
	}

	public void setJumphomepage(JumpHomePage jumphomepage) {
		this.jumphomepage = jumphomepage;
	}

	public String getDbUsername() {
		return dbUsername;
	}

	public void setDbUsername(String dbUsername) {
		this.dbUsername = dbUsername;
	}

	public String getDbPassword() {
		return dbPassword;
	}

	public void setDbPassword(String dbPassword) {
		this.dbPassword = dbPassword;
	}
	
	public void replaceConfigFile(ConfigFile cf){
		if (cf!=null && this.configFiles != null){
			if (this.configFiles.size()== 0 || !this.configFiles.contains(cf.getStandardName())) {
				this.configFiles.add(cf);
				return;
			}
			for (int i=0;i<this.configFiles.size();i++){
				if (this.configFiles.get(i).getStandardName().equals(cf.getStandardName())) {
					this.configFiles.remove(i);
					this.configFiles.add(cf);
				}
			}
		}
	}
	
	public String getLabel() {
		return label;
	}

	public void setLabel(String label) {
		this.label = label;
	}
	
	public String getText(){
		if (this.label!= null && !this.label.equals("")) return this.label;
		else return this.standardName;
	}
	
	public  void writeToFile(String filePath, String content) throws Exception{
		File f = new File(filePath);
		if (!f.getParentFile().exists()) {
			f.getParentFile().mkdirs();
		}
		f.createNewFile();
		try (Writer fw = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(f.getAbsolutePath()),"UTF-8"))){			
	        fw.write(content,0,content.length());
		}
	}

	public List<MysqlTwoDomainsDBDefinitionGenerator> getMyTwoDBGenerators() {
		return myTwoDBGenerators;
	}

	public void setMyTwoDBGenerators(List<MysqlTwoDomainsDBDefinitionGenerator> myTwoDBGenerators) {
		this.myTwoDBGenerators = myTwoDBGenerators;
	}

	public String getDbType() {
		return dbType;
	}

	public void setDbType(String dbType) {
		this.dbType = dbType;
	}

	public EasyUIHomePageTemplate getHomepage() {
		return homepage;
	}

	public void setHomepage(EasyUIHomePageTemplate homepage) {
		this.homepage = homepage;
	}
	
	public String toString(){
		return JSONObject.fromObject(this).toString();
	}
	
	public static File createPathFile(String path){
		try {
			File f = new File(path);
			if (!f.getParentFile().exists()) {
				f.getParentFile().mkdirs();
			}
			f.createNewFile();
			return f;
		}catch (Exception e){
			e.printStackTrace();
			return null;
		}
	}

	public List<List<Domain>> getDataDomains() {
		return dataDomains;
	}

	public void setDataDomains(List<List<Domain>> dataDomains) {
		this.dataDomains = dataDomains;
	}
	
	public void addDataDomains(ArrayList<Domain> datas){
		this.dataDomains.add(datas);
	}

	public String getExcelTemplateName() {
		return excelTemplateName;
	}

	public void setExcelTemplateName(String excelTemplateName) {
		this.excelTemplateName = excelTemplateName;
	}

	public String getExcelTemplateFolder() {
		return excelTemplateFolder;
	}

	public void setExcelTemplateFolder(String excelTemplateFolder) {
		this.excelTemplateFolder = excelTemplateFolder;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getSubTitle() {
		return subTitle;
	}

	public void setSubTitle(String subTitle) {
		this.subTitle = subTitle;
	}

	public String getFooter() {
		return footer;
	}

	public void setFooter(String footer) {
		this.footer = footer;
	}

	public String getCrossOrigin() {
		return crossOrigin;
	}

	public void setCrossOrigin(String crossOrigin) {
		this.crossOrigin = crossOrigin;
	}

	public Set<Independent> getIndependents() {
		return independents;
	}

	public void setIndependents(Set<Independent> independents) {
		this.independents = independents;
	}

	public Set<IndependentConfig> getIndependentConfigs() {
		return independentConfigs;
	}

	public void setIndependentConfigs(Set<IndependentConfig> independentConfigs) {
		this.independentConfigs = independentConfigs;
	}
}
